package cis350.pcr.activities;

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import cis350.pcr.CodeLookupDB;
import cis350.pcr.R;
import cis350.pcr.SearchDB;
import cis350.pcr.SearchHandler;
import cis350.pcr.R.id;
import cis350.pcr.R.layout;

import com.loopj.android.http.AsyncHttpResponseHandler;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.NumberPicker;
import android.widget.TextView;

public class SettingsActivity extends Activity {
	private ProgressDialog dataloadingDialog;

	private int progress;
	private int started;
	private int numDepartments;

	private String loadingMsgHeader = "Loading Data from Server...\n";
	private String deptResponse;

	private boolean httpFailed;

	private SearchHandler handler;
	private CodeLookupDB codeDB;
	private SearchDB searchDB;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.settings);
		codeDB = new CodeLookupDB(this);
		searchDB = new SearchDB(this);
		handler = new SearchHandler(this);

		ActionBar actionBar = getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(false);
		actionBar.setTitle("Settings");
		updateDatabaseSize();
		updateCacheSize();
	}

	@Override
	public void onStop() {
		super.onStop();
		codeDB.close();
		searchDB.close();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			// app icon in action bar clicked; go home
			Intent intent = new Intent(this, SearchActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			startActivity(intent);
			return true;

		default:
			return super.onOptionsItemSelected(item);
		}

	}

	public void onLoadClick(View view) {
		// delete database
		Log.d("deleting data", "data");
		codeDB.deleteDatabase(this);
		updateDatabaseSize();

		Log.d("OnLoadClick", "Started");
		httpFailed = false;
		progress = 0;
		dataloadingDialog = new ProgressDialog(this);
		dataloadingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		dataloadingDialog.setCancelable(false);
		dataloadingDialog.setMessage(loadingMsgHeader + "Initializing");
		dataloadingDialog.setProgress(progress);
		dataloadingDialog.setMax(numDepartments);
		dataloadingDialog.show();
		dataloadingDialog.setOnCancelListener(new OnCancelListener() {

			public void onCancel(DialogInterface dialog) {
				// actually could set running = false; right here, but I'll
				// stick to contract.
				updateDatabaseSize();

			}
		});

		// department
		handler.get("depts", null, new AsyncHttpResponseHandler() {

			@Override
			public void onStart() {
				Log.d("starting", "starting");
			}

			@Override
			public void onFailure(Throwable e) {
				e.printStackTrace();
				Log.d("error", "http failed");
				httpFailed = true;
			}

			public void onSuccess(String response) {
				Log.d("All departments", "Received JSON");
				deptResponse = response;
				try {
					JSONObject toplevel = new JSONObject(response);
					JSONArray depts = toplevel.getJSONObject("result").getJSONArray("values");

					numDepartments = depts.length();
					dataloadingDialog.setMax(numDepartments + 1);
				} catch (JSONException e) {
					e.printStackTrace();
				}

				new Thread(new Runnable() {
					public void run() {
						codeDB.addDepartments(deptResponse);
						Log.d("Departments", "Completed");
					}
				}).start();
			}

			@Override
			public void onFinish() {
			}
		});

		if (!httpFailed) {
			// instructor
			handler.get("instructors", null, new AsyncHttpResponseHandler() {
				@Override
				public void onStart() {
					Log.d("starting", "starting");
				}

				@Override
				public void onFailure(Throwable e) {
					e.printStackTrace();
					Log.d("error", "http failed");
				}

				public void onSuccess(final String response) {
					Log.d("Instructors", "Received JSON");
					dataloadingDialog.setMessage(loadingMsgHeader + "Instructors");

					new Thread(new Runnable() {
						public void run() {
							codeDB.addInstructors(response);
							progress++;
							runOnUiThread(new Runnable() {
								public void run() {
									dataloadingDialog.setProgress(progress);
									ParseAllDepartments(deptResponse);
								}
							});
						}
					}).start();
				}

				@Override
				public void onFinish() {
				}
			});
		}

		if (httpFailed) {
			dataloadingDialog.dismiss();
			showAlert("Unable to connect to server. Would you like to retry?");
		}

	}

	public void ParseAllDepartments(String response) {
		final ExecutorService executor = Executors.newFixedThreadPool(8);
		started = 0;

		try {
			JSONObject toplevel = new JSONObject(response);
			JSONArray depts = toplevel.getJSONObject("result").getJSONArray("values");

			for (int i = 0; i < depts.length(); i++) {
				JSONObject entry = depts.getJSONObject(i);

				String path = entry.getString("path");
				final String name = entry.getString("name");
				final String code = entry.getString("id");

				handler.get(path, null, new AsyncHttpResponseHandler() {
					@Override
					public void onStart() {
						Log.d("starting", "starting");
					}

					@Override
					public void onFailure(Throwable e) {
						e.printStackTrace();
						Log.d("http failed", "loading individual dept");
						httpFailed = true;
						progress++;
					}

					@Override
					public void onSuccess(final String response) {
						started++;
						if (started % 10 == 0)
							Log.d("Department Started", name + " " + started + "/" + numDepartments);

						executor.execute(new Runnable() {
							public void run() {
								codeDB.addCourseHistory(response, code);
								progress++;

								runOnUiThread(new Runnable() {
									public void run() {
										dataloadingDialog.setProgress(progress);
										dataloadingDialog.setMessage(loadingMsgHeader + name);

									}
								});

								if (progress % 10 == 0)
									Log.d("Department Finished", name + " " + progress + "/" + numDepartments);
								if (progress == dataloadingDialog.getMax()) {
									codeDB.close();
									runOnUiThread(new Runnable() {
										public void run() {
											executor.shutdown();
											dataloadingDialog.dismiss();

											updateDatabaseSize();
										}
									});

								}
							}
						});

					}

					@Override
					public void onFinish() {
					}
				});
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}

		if (httpFailed) {
			showAlert("Some data faild to load. Would you like to retry?");
		}
	}


	public void onClearCache(View view) {
		searchDB.deleteDatabase(this);
		updateCacheSize();
	}

	private void showAlert(String msg) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(msg).setCancelable(false).setNegativeButton("No", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
			}
		}).setPositiveButton("Yes", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				onLoadClick(null);
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}

	public void updateDatabaseSize() {
		int numCourses = codeDB.getNumCourses();
		int numProfs = codeDB.getNumProfs();
		int numDepts = codeDB.getNumDepts();
		long size = codeDB.getDatabaseSize(this);
		
		double mb = (double)size / (1024 * 1024);
		int temp =(int)(mb*100);
	    mb =  (double)temp/100;
	    
		TextView t = (TextView) findViewById(R.id.deptDataText);
		t.setText(numDepts + "");
		
		t = (TextView) findViewById(R.id.courseDataText);
		t.setText(numCourses + "");
		
		t = (TextView) findViewById(R.id.instructorDataText);
		t.setText(numProfs + "");
		
		t = (TextView) findViewById(R.id.sizeDataText);
		t.setText(mb + "MB");
	}
	
	public void updateCacheSize() {
		int items = searchDB.getItemCount();
		long size = searchDB.getDatabaseSize(this);
		
		double kb = (double)size / (1024);
		int temp =(int)(kb*100); 
	    kb =  (double)temp/100;
	    

		TextView t = (TextView) findViewById(R.id.recentItemDataText);
		t.setText(items + "");
		
		t = (TextView) findViewById(R.id.recentSizeDataText);
		t.setText(kb + "KB");
	}
}